package com.ywf.corebase.framework.handler;

import com.ywf.corebase.common.exception.BusinessException;
import com.ywf.corebase.common.exception.UserLoginException;
import com.ywf.corebase.common.utils.RequestContextUtil;
import com.ywf.corebase.framework.annotation.ExceptionCode;
import com.ywf.corebase.framework.enums.ResultCodeEnum;
import com.ywf.corebase.framework.result.R;
import org.springframework.data.redis.RedisConnectionFailureException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.client.HttpClientErrorException;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Field;

/**
 * ClassName:GlobalExceptionHandler
 * Package:com.ywf.myproject.common.exception
 * Description:
 *
 * @Date:2021/2/28 18:02
 * @Author:YWF
 */
@ControllerAdvice
public class GlobalExceptionHandler {


    /**
     * 通用异常处理方法
     * @param e
     * @return
     */
    @ExceptionHandler(Exception.class)
    @ResponseBody
    public R error (Exception e){
        e.printStackTrace();
        return R.error();
    }

    /**
     * 空指针异常处理类
     * @param e
     * @return
     */
    @ExceptionHandler(NullPointerException.class)
    @ResponseBody
    public R error(NullPointerException e){
        HttpServletRequest request = RequestContextUtil.getRequest();
        e.printStackTrace();
        return R.setResult(ResultCodeEnum.NULL_POINT);
    }

    /**
     * Http状态码错误异常
     * @param e
     * @return
     */
    @ExceptionHandler(HttpClientErrorException.class)
    @ResponseBody
    public R error(HttpClientErrorException e){
        e.printStackTrace();
        return R.setResult(ResultCodeEnum.HTTP_CLIENT_ERROR);
    }

    /**
     * 自定义异常处理类
     * @param e
     * @return
     */
    @ExceptionHandler(BusinessException.class)
    @ResponseBody
    public R error(BusinessException e){
        e.printStackTrace();
        return R.error().message(e.getMessage()).code(e.getCode());
    }

    @ExceptionHandler(IllegalArgumentException.class)
    @ResponseBody
    public R error(IllegalArgumentException e){
        e.printStackTrace();
        return R.error().message(e.getMessage());
    }

    @ExceptionHandler({RedisConnectionFailureException.class, UserLoginException.class})
    @ResponseBody
    public R error(RedisConnectionFailureException e){
        e.printStackTrace();
        return R.setResult(ResultCodeEnum.REDIS_SERVICES_NOT_START);
    }

    @ExceptionHandler(MissingServletRequestParameterException.class)
    @ResponseBody
    public R error(MissingServletRequestParameterException e){
        HttpServletRequest request = RequestContextUtil.getRequest();
        return R.error().message("参数缺失："+e.getParameterName());
    }

    @ExceptionHandler(MethodArgumentNotValidException.class)
    @ResponseBody
    public R error(MethodArgumentNotValidException e) throws NoSuchFieldException {
        //从异常第项中拿到错误信息
        String defaultMessage = e.getBindingResult().getAllErrors().get(0).getDefaultMessage();
        //拿到参数的对象
        Class<?> parameterType = e.getParameter().getParameterType();
        //拿到错误的参数字段
        String fieldName = e.getBindingResult().getFieldError().getField();
        Field field = parameterType.getDeclaredField(fieldName);
        // 获取Field对象上的自定义注解
        ExceptionCode annotation = field.getAnnotation(ExceptionCode.class);
        if (annotation!=null){
            return R.error().code(annotation.value()).message(annotation.message()).data(defaultMessage);
        }
        // 没有注解就提取错误提示信息进行返回统一错误码
        return R.setResult(ResultCodeEnum.PARAM_ERROR);
    }

}
